package simpledb.algorithm.join;

import simpledb.execution.JoinPredicate;
import simpledb.execution.OpIterator;
import simpledb.storage.Tuple;
import simpledb.storage.TupleDesc;
import simpledb.storage.TupleIterator;

import java.util.ArrayList;
import java.util.List;

/**
 * 嵌套循环连接（Nested Loop Join）是一种最基础的连接算法。
 * 它通过双重循环遍历两个输入源（外层表与内层表），对每一对元组应用连接谓词，
 * 若满足条件则将其合并后加入结果集。
 *
 * 该实现适用于教学用途，在实际数据库中通常效率较低。
 */
public class NestedLoopJoin extends JoinStrategy {

    /**
     * 构造函数：创建一个嵌套循环连接算子。
     *
     * @param child1 左侧输入源（外层表）
     * @param child2 右侧输入源（内层表）
     * @param td 合并后的输出结构（child1 + child2 的字段）
     * @param joinPredicate 用于判断两个元组是否匹配的连接谓词
     */
    public NestedLoopJoin(final OpIterator child1, final OpIterator child2, final TupleDesc td,
                          final JoinPredicate joinPredicate) {
        super(child1, child2, td, joinPredicate);
    }

    /**
     * 执行嵌套循环连接操作。
     *
     * 算法步骤：
     * 1. 遍历左侧输入源中的每一个元组；
     * 2. 对于每个左表元组，重置右侧输入源并遍历其中的每一个元组；
     * 3. 如果左右元组满足连接条件，则将它们合并后加入结果列表；
     * 4. 最终返回包含所有匹配元组的迭代器。
     *
     * 注意：这个算法时间复杂度为 O(n*m)，在大数据量下性能较差。
     *
     * @return 包含连接结果的 TupleIterator
     */
    @Override
    public TupleIterator doJoin() {
        final List<Tuple> tuples = new ArrayList<>();

        try {
            child1.rewind(); // 从头开始读取左表
            while (child1.hasNext()) {
                final Tuple lTuple = child1.next();

                child2.rewind(); // 每次换左表元组时重置右表
                while (child2.hasNext()) {
                    final Tuple rTuple = child2.next();

                    // 判断是否满足连接条件
                    if (this.joinPredicate.filter(lTuple, rTuple)) {
                        // 满足条件 -> 合并元组并加入结果集
                        tuples.add(mergeTuple(lTuple, rTuple, this.td));
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("嵌套循环连接过程中发生异常");
        }

        // 返回一个可以遍历连接结果的迭代器
        return new TupleIterator(this.td, tuples);
    }

    /**
     * 关闭连接策略的相关资源。
     * 当前实现未涉及外部资源，因此方法体为空。
     */
    @Override
    public void close() {
        // 当前未使用任何需要显式关闭的资源，如内存池、文件句柄等
    }
}
